﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using static Utility.WinAPI;

namespace WallpaperEngine
{
    public class Hook
    {
        IntPtr hook;
        IntPtr hookTarget;
        Thread hookThread;
        Queue<uint> hookMessage;
        
        public Hook(IntPtr targetHandle)
        {
            hook = IntPtr.Zero; 

            hookTarget = IntPtr.Zero;

            hookMessage = new Queue<uint>();

            hookThread = new Thread(() =>
            {
                while (true)
                {
                    uint Msg = DequeueHookMessage();
                    if (hook != IntPtr.Zero)
                    {
                        GetCursorPos(out System.Drawing.Point pt);
                        PostMessage(hookTarget, Msg, 0, MakeLong((short)pt.X, (short)pt.Y));
                        Debug.Print($"消息已发出!消息:{Msg}");
                    }
                }
            })
            {
                Priority = ThreadPriority.Highest,
                IsBackground = true,
            };
            hookThread.Start();

            Debug.Print($"钩子已启动,目标句柄:{targetHandle}");
            hook = SetWindowsHookEx(HookFlags.WH_MOUSE_LL, ((nCode, wParam, lParam) =>
            {
                EnqueueHookMessage((uint)wParam);
                return CallNextHookEx(hook, nCode, (IntPtr)wParam, lParam);
            }), IntPtr.Zero, 0);
            hookTarget = targetHandle;
        }

        public void Stop()
        {
            if (hook != IntPtr.Zero)
            {
                UnhookWindowsHookEx(hook);
                hook = IntPtr.Zero;
                hookTarget = IntPtr.Zero;
                Debug.Print("钩子已卸载!");
            }
        }

        void EnqueueHookMessage(uint message)
        {
            lock (hookMessage)
            {
                hookMessage.Enqueue(message);
                Monitor.Pulse(hookMessage);
            }
        }

        uint DequeueHookMessage()
        {
            lock (hookMessage)
            {
                if (hookMessage.Count == 0)
                {
                    Monitor.Wait(hookMessage);
                }
                return hookMessage.Dequeue();
            }
        }
    }
}
